pygrub: factor generic Grub functionality into GrubConf base classes
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 23 Nov 2009 08:05:49 +0000 (08:05 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 23 Nov 2009 08:05:49 +0000 (08:05 +0000)
and inherit from these classes to implement Grub-legacy functionality.

Use a tuple of (parser-object,configuration-file) in pygrub to allow
for multiple parsers.

Makes way for grub2 support.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
tools/pygrub/src/GrubConf.py
tools/pygrub/src/pygrub

index 694f5d5dd2cc2ffed679e7d7c90ebac37ed8e835..12f421996e06711facecdec14b93baee76ea9bd1 100644 (file)
@@ -78,7 +78,7 @@ class GrubDiskPart(object):
         self._part = int(val)
     part = property(get_part, set_part)
 
-class GrubImage(object):
+class _GrubImage(object):
     def __init__(self, lines):
         self.reset(lines)
 
@@ -89,30 +89,14 @@ class GrubImage(object):
                 "  args: %s\n"
                 "  initrd: %s\n" %(self.title, self.root, self.kernel,
                                    self.args, self.initrd))
+    def _parse(self, lines):
+        map(self.set_from_line, lines)
 
     def reset(self, lines):
         self._root = self._initrd = self._kernel = self._args = None
         self.title = ""
         self.lines = []
-        map(self.set_from_line, lines)
-
-    def set_from_line(self, line, replace = None):
-        (com, arg) = grub_exact_split(line, 2)
-
-        if self.commands.has_key(com):
-            if self.commands[com] is not None:
-                setattr(self, self.commands[com], arg.strip())
-            else:
-                logging.info("Ignored image directive %s" %(com,))
-        else:
-            logging.warning("Unknown image directive %s" %(com,))
-
-        # now put the line in the list of lines
-        if replace is None:
-            self.lines.append(line)
-        else:
-            self.lines.pop(replace)
-            self.lines.insert(replace, line)
+        self._parse(lines)
 
     def set_root(self, val):
         self._root = GrubDiskPart(val)
@@ -141,6 +125,28 @@ class GrubImage(object):
         return self._initrd
     initrd = property(get_initrd, set_initrd)
 
+class GrubImage(_GrubImage):
+    def __init__(self, lines):
+        _GrubImage.__init__(self, lines)
+    
+    def set_from_line(self, line, replace = None):
+        (com, arg) = grub_exact_split(line, 2)
+
+        if self.commands.has_key(com):
+            if self.commands[com] is not None:
+                setattr(self, self.commands[com], arg.strip())
+            else:
+                logging.info("Ignored image directive %s" %(com,))
+        else:
+            logging.warning("Unknown image directive %s" %(com,))
+
+        # now put the line in the list of lines
+        if replace is None:
+            self.lines.append(line)
+        else:
+            self.lines.pop(replace)
+            self.lines.insert(replace, line)
+
     # set up command handlers
     commands = { "title": "title",
                  "root": "root",
@@ -149,9 +155,8 @@ class GrubImage(object):
                  "initrd": "initrd",
                  "chainloader": None,
                  "module": None}
-        
 
-class GrubConfigFile(object):
+class _GrubConfigFile(object):
     def __init__(self, fn = None):
         self.filename = fn
         self.images = []
@@ -164,50 +169,7 @@ class GrubConfigFile(object):
             self.parse()
 
     def parse(self, buf = None):
-        if buf is None:
-            if self.filename is None:
-                raise ValueError, "No config file defined to parse!"
-
-            f = open(self.filename, 'r')
-            lines = f.readlines()
-            f.close()
-        else:
-            lines = buf.split("\n")
-
-        img = []
-        for l in lines:
-            l = l.strip()
-            # skip blank lines
-            if len(l) == 0:
-                continue
-            # skip comments
-            if l.startswith('#'):
-                continue
-            # new image
-            if l.startswith("title"):
-                if len(img) > 0:
-                    self.add_image(GrubImage(img))
-                img = [l]
-                continue
-                
-            if len(img) > 0:
-                img.append(l)
-                continue
-
-            (com, arg) = grub_exact_split(l, 2)
-            if self.commands.has_key(com):
-                if self.commands[com] is not None:
-                    setattr(self, self.commands[com], arg.strip())
-                else:
-                    logging.info("Ignored directive %s" %(com,))
-            else:
-                logging.warning("Unknown directive %s" %(com,))
-                
-        if len(img) > 0:
-            self.add_image(GrubImage(img))
-
-        if self.hasPassword():
-            self.setPasswordAccess(False)
+        raise RuntimeError, "unimplemented parse function"   
 
     def hasPasswordAccess(self):
         return self.passwordAccess
@@ -285,7 +247,56 @@ class GrubConfigFile(object):
         commands[c] = None
     del c
 
+class GrubConfigFile(_GrubConfigFile):
+    def __init__(self, fn = None):
+        _GrubConfigFile.__init__(self,fn)
+        
+    def parse(self, buf = None):
+        if buf is None:
+            if self.filename is None:
+                raise ValueError, "No config file defined to parse!"
+
+            f = open(self.filename, 'r')
+            lines = f.readlines()
+            f.close()
+        else:
+            lines = buf.split("\n")
 
+        img = []
+        for l in lines:
+            l = l.strip()
+            # skip blank lines
+            if len(l) == 0:
+                continue
+            # skip comments
+            if l.startswith('#'):
+                continue
+            # new image
+            if l.startswith("title"):
+                if len(img) > 0:
+                    self.add_image(GrubImage(img))
+                img = [l]
+                continue
+                
+            if len(img) > 0:
+                img.append(l)
+                continue
+
+            (com, arg) = grub_exact_split(l, 2)
+            if self.commands.has_key(com):
+                if self.commands[com] is not None:
+                    setattr(self, self.commands[com], arg.strip())
+                else:
+                    logging.info("Ignored directive %s" %(com,))
+            else:
+                logging.warning("Unknown directive %s" %(com,))
+                
+        if len(img) > 0:
+            self.add_image(GrubImage(img))
+
+        if self.hasPassword():
+            self.setPasswordAccess(False)
+    
 if __name__ == "__main__":
     if sys.argv < 2:
         raise RuntimeError, "Need a grub.conf to read"
index 1ed2606324001b9dd6ff2287625519de58e93682..71dd0869536b55a73f99ba6cc744d214d7cdcc65 100644 (file)
@@ -371,17 +371,17 @@ class Grub:
             raise RuntimeError, "Unable to access %s" %(fn,)
 
         if platform.machine() == 'ia64':
-            self.cf = grub.LiloConf.LiloConfigFile()
-            # common distributions
-            file_list = ("/efi/debian/elilo.conf", "/efi/gentoo/elilo.conf", 
-                         "/efi/redflag/elilo.conf", "/efi/redhat/elilo.conf", 
-                         "/efi/SuSE/elilo.conf",)
-            # fallbacks
-            file_list += ("/efi/boot/elilo.conf", "/elilo.conf",)
+            cfg_list = map(lambda x: (x,grub.LiloConf.LiloConfigFile), 
+                           # common distributions
+                           ["/efi/debian/elilo.conf", "/efi/gentoo/elilo.conf", 
+                            "/efi/redflag/elilo.conf", "/efi/redhat/elilo.conf", 
+                            "/efi/SuSE/elilo.conf",] + 
+                           # fallbacks
+                           ["/efi/boot/elilo.conf", "/elilo.conf",])
         else:
-            self.cf = grub.GrubConf.GrubConfigFile()
-            file_list = ("/boot/grub/menu.lst", "/boot/grub/grub.conf",
-                         "/grub/menu.lst", "/grub/grub.conf")
+            cfg_list = map(lambda x: (x,grub.GrubConf.GrubConfigFile),
+                           ["/boot/grub/menu.lst", "/boot/grub/grub.conf",
+                            "/grub/menu.lst", "/grub/grub.conf"])
 
         if not fs:
             # set the config file and parse it
@@ -389,8 +389,10 @@ class Grub:
             self.cf.parse()
             return
 
-        for f in file_list:
+        for f,parser in cfg_list:
             if fs.file_exists(f):
+                print >>sys.stderr, "Using %s to parse %s" % (parser,f)
+                self.cf = parser()
                 self.cf.filename = f
                 break
         if self.cf.filename is None: